//
// Super Standard Template Library
//
// Copyright 1997-2008 Matt T. Yourst <yourst@yourst.com>
//
// This program is free software; it is licensed under the
// GNU General Public License, Version 2.
//

#include <globals.h>
#include <superstl.h>

// For debugging of messages before crashes:
bool force_synchronous_streams = false;

namespace superstl {
  //
  // odstream
  //
  odstream::odstream() {
    fd = -1;
    buf = null;
    bufsize = 0;
    tail = 0;
    close_on_destroy = 1;
    ringbuf_mode = 0;
    ringbuf = null;
    ringbuf_tail = 0;
    chain = null;
    offset = 0;
  }

  odstream::~odstream() {
    close();
  }

  bool odstream::open(const char* filename, bool append, int bufsize) {
    if (fd >= 0) close();
    fd = sys_open(filename, O_RDWR | O_CREAT | ((append) ? O_APPEND : O_TRUNC) | O_LARGEFILE, 0644);
    if (fd < 0) return false;
    buf = null;
    this->bufsize = 0;
    setbuf(bufsize);
    close_on_destroy = 1;
    ringbuf_mode = 0;
    ringbuf = null;
    chain = null;
    offset = 0;
    return true;
  }

  int odstream::setbuf(int newbufsize) {
    if (fd < 0) return 0;
    if (bufsize == newbufsize) return bufsize;
    if (buf) delete buf;
    bufsize = newbufsize;
    if (!bufsize) return 0;
    tail = 0;
    buf = new byte[bufsize];
    return bufsize;
  }

  bool odstream::open(int fd, int bufsize) {
    if (this->fd >= 0) close();
    this->fd = fd;
    buf = null;
    this->bufsize = 0;
    setbuf(bufsize);
    close_on_destroy = 0;
    ringbuf_mode = 0;
    ringbuf = null;
    chain = null;
    offset = 0;
    return ok();
  }

  void odstream::close() {
    if (fd < 0) return;
    if (ringbuf_mode) set_ringbuf_mode(0);
    flush();
    if (buf) delete[] buf;
    buf = null;
    tail = 0;
    if (close_on_destroy) sys_close(fd);
    fd = -1;
  }

  //
  // Copy all writes to secondary stream 'chain'.
  //
  void odstream::setchain(odstream* chain) {
    this->chain = chain;
  }

  //
  // If tail mode is enabled, every time the buffer fills,
  // copy it to a backup buffer of the same size, then
  // discard the current buffer, rather than writing its
  // contents to the backing file.
  //
  // The first time tail mode is enabled, the buffer
  // is flushed to the file first before starting
  // this behavior. Similarly, when disabling tail
  // mode, both the backup buffer and the real
  // buffer are flushed to the stream (otherwise
  // there would be no way to get the saved data).
  // Flushes while in tail mode are no-ops.
  //
  // This mode is useful for log files where massive
  // amounts of data would be generated but only
  // the very last batch of log entries before a
  // crash or assert failure are interesting.
  //
  void odstream::set_ringbuf_mode(bool new_ringbuf_mode) {
    if (fd < 0) return;
    if (ringbuf_mode == new_ringbuf_mode) return;

    if (new_ringbuf_mode) {
      // Transition from off -> on: first flush, then alloc
      flush();
      assert(!ringbuf);
      
      ringbuf = new byte[bufsize];
      memset(ringbuf, 0, bufsize);
      ringbuf_tail = 0;
      ringbuf_mode = 1;
    } else {
      // Transition from on -> off: turn off, then flush
      assert(ringbuf);
      sys_write(fd, ringbuf, ringbuf_tail);
      delete ringbuf;


      ringbuf = null;
      ringbuf_tail = 0;

      ringbuf_mode = 0;
      // Flush out last part of circular buffer: 
      flush();
    }
  }

  int odstream::write(const void* data, int count) {
    if unlikely (!ok()) return 0;
    if unlikely (!buf) {
      return sys_write(fd, data, count);
      if (chain) chain->write(data, count);
    }

    byte* p = (byte*)data;

    int total = 0;

    if unlikely (chain) chain->write(data, count);

    while (count) {
      int n = min(bufsize - tail, count);
      memcpy(buf + tail, p, n);
      tail += n;
      assert(inrange(tail, 0, bufsize));
      count -= n;
      total += n;
      p += n;
      if unlikely (!n) {
        flush();
      }
    }

    offset += total;

    if unlikely (force_synchronous_streams) flush();

    return total;
  }

  void odstream::flush() {
    if unlikely (chain) chain->flush();

    if unlikely (ringbuf_mode) {
      // Ignore partial flushes
      if (tail < bufsize) return;

      byte* temp = ringbuf;
      ringbuf = buf;
      buf = temp;

      ringbuf_tail = tail;
      tail = 0;
      return;
    }

    if likely (buf) {
      int rc = 0;
      if (tail) rc = sys_write(fd, buf, tail);
      tail = 0;
    }
  }

  W64 odstream::seek(W64 pos, int whence) {
    flush();
    offset = sys_seek(fd, pos, whence);    
    return offset;
  }

  W64 odstream::where() const {
    return offset;
  }

  //
  // stringbuf
  //

  void stringbuf::reset(int length) {
    if (buf && (buf != smallbuf))
      delete[] buf;
    buf = (length <= stringbuf_smallbufsize) ? smallbuf : new char[length];
    length = max(length, stringbuf_smallbufsize);
    p = buf;
    this->length = length;
    p[0] = 0;
  }

  void stringbuf::resize(int newlength) {
    if (newlength > length) {
      int strlength = (p-buf);
      if (buf == smallbuf) {
        buf = new char[newlength];
        assert(strlength < newlength);
        memcpy(buf, smallbuf, strlength);
        buf[strlength] = 0;
      } else {
        assert(strlength < newlength);
        char* newbuf = new char[newlength];
        memcpy(newbuf, buf, strlength);
        delete[] buf;
        buf = newbuf;
      }
      length = newlength;
      p = buf + strlength;
      buf[strlength] = 0;
    }
  }

  void stringbuf::reserve(int extra) {
    int newlength = ((p - buf) + extra + 1);
    // Round up to next power of two:
    newlength = 1 << (msbindex(newlength) + 1);
    if (remaining() < extra) resize(newlength);
    assert(remaining() >= extra);
  }

  stringbuf::~stringbuf() {
    if (buf && (buf != smallbuf))
      delete[] buf;
    buf = null;
    p = null;
    length = 0;
  }

  //
  // Writers
  //
  stringbuf& operator <<(stringbuf& os, const char* v) {
    if unlikely (!v) v = "<null>";
    int bytes = strlen(v) + 1;
    os.reserve(bytes);
    memcpy(os.p, v, bytes);
    os.p += bytes - 1;
    return os;
  }

  stringbuf& operator <<(stringbuf& os, char v) {
    os.reserve(2);
    os.p[0] = v;
    os.p[1] = 0;
    os.p++;
    return os;
  }

  stringbuf& operator <<(stringbuf& os, const bitstring& bs) {
    if (bs.reverse) {
      // LSB first:
      for (int i = 0; i < bs.n; i++) os << (char)(bit(bs.bits, i) + '0');
    } else {
      // MSB first (default):
      for (int i = bs.n-1; i >= 0; i--) os << (char)(bit(bs.bits, i) + '0');
    }
    
    return os;
  }

  stringbuf& operator <<(stringbuf& os, const bitmaskstring& bs) {
    if (bs.reverse) {
      // LSB first:
      for (int i = 0; i < bs.n; i++) os << (char)(bit(bs.mask, i) ? (bit(bs.bits, i) + '0') : 'x');
    } else {
    // MSB first (default):
      for (int i = bs.n-1; i >= 0; i--) os << (char)(bit(bs.mask, i) ? (bit(bs.bits, i) + '0') : 'x');
    }

    return os;
  }

  stringbuf& operator <<(stringbuf& os, const hexstring& hs) {
    static const char* hexdigits = "0123456789abcdef";
    char buf[128+1];
    assert(hs.n <= 64);

    int n = ceil(hs.n, 4) / 4;

    W64 v = hs.value;
    int j = n-1;
    buf[n] = 0;

    while (j >= 0) {
      buf[j--] = hexdigits[v & 0xf];
      v >>= 4;
    }

    os << buf;
    return os;
  }
  
  stringbuf& operator <<(stringbuf& os, const bytestring& bs) {
    foreach (i, bs.n) {
      os << hexstring(bs.bytes[i], 8);
      if (((i % bs.splitat) == (bs.splitat-1)) && (i != bs.n-1)) 
        os << endl; 
      else if (i != bs.n-1)
        os << " ";
    }

    return os;
  }

  stringbuf& operator <<(stringbuf& os, const bytemaskstring& bs) {
    foreach (i, bs.n) {
      if (bit(bs.mask, i))
        os << hexstring(bs.bytes[i], 8);
      else os << "xx";
      if (((i % bs.splitat) == (bs.splitat-1)) && (i != bs.n-1)) 
        os << endl; 
      else if (i != bs.n-1)
        os << " ";
    }

    return os;
  }

  stringbuf& operator <<(stringbuf& os, const intstring& is) {
    char buf[128];
    int len = format_integer(buf, sizeof(buf), is.value);
    bool leftalign = (is.width < 0);
    int width = (is.width) ? abs(is.width) : len;

    int reqbytes = max(len, width) + 1;
    os.reserve(reqbytes);

    if (leftalign) {
      memcpy(os.p, buf, len);
      os.p += len;
      width = max(width - len, 0);
      memset(os.p, ' ', width);
      os.p += width;
    } else {
      width = max(width - len, 0);
      memset(os.p, ' ', width);
      os.p += width;
      memcpy(os.p, buf, len);
      os.p += len;
    }
    *os.p = 0;

    return os;
  }

  stringbuf& operator <<(stringbuf& os, const floatstring& fs) {
    char buf[128];
    int len = format_float(buf, sizeof(buf), fs.value, fs.precision);
    bool leftalign = (fs.width < 0);
    int width = (fs.width) ? abs(fs.width) : len;

    int reqbytes = max(len, width) + 1;
    os.reserve(reqbytes);

    if (leftalign) {
      memcpy(os.p, buf, len);
      os.p += len;
      width = max(width - len, 0);
      memset(os.p, ' ', width);
      os.p += width;
    } else {
      width = max(width - len, 0);
      memset(os.p, ' ', width);
      os.p += width;
      memcpy(os.p, buf, len);
      os.p += len;
    }
    *os.p = 0;

    return os;
  }

  stringbuf& operator <<(stringbuf& os, const padstring& s) {
    int len = strlen(s.value);
    bool leftalign = (s.width < 0);
    int width = (s.width) ? abs(s.width) : len;

    int reqbytes = max(len, width) + 1;
    os.reserve(reqbytes);

    if (leftalign) {
      memcpy(os.p, s.value, len);
      os.p += len;
      width = max(width - len, 0);
      memset(os.p, s.pad, width);
      os.p += width;
    } else {
      width = max(width - len, 0);
      memset(os.p, s.pad, width);
      os.p += width;
      memcpy(os.p, s.value, len);
      os.p += len;
    }
    *os.p = 0;

    return os;
  }

  stringbuf& operator <<(stringbuf& os, const substring& s) {
    os.reserve(s.length + 1);
    memcpy(os.p, s.str, s.length);
    os.p += s.length;
    *os.p = 0;

    return os;
  }

  //
  // String tools
  //
  int stringsubst(stringbuf& sb, const char* pattern, const char* find, const char* replace) {
    sb.reset();

    if (strequal(find, replace)) {
      // Prevent infinite recursion if the caller does something stupid:
      sb << pattern;
      return 0;
    }

    int n = 0;
    for (;;) {
      const char* pp = strstr(pattern, find);
      if (!pp) {
        sb << pattern;
        return n;
      }

      int presize =  pp - pattern;
    
      sb << substring(pattern, 0, pp - pattern);
      sb << replace;
      pattern = pp + strlen(find);
      n++;
    }

    return n;
  }

  int stringsubst(stringbuf& sb, const char* pattern, const char* find[], const char* replace[], int substcount) {
    stringbuf sbwork[2];
    int alt = 0;

    int iters = 0;

    int nn = 0;

    for (;;) {
      int n = 0;
      foreach (i, substcount) {
        sbwork[alt].reset();
        n += stringsubst(sbwork[alt], (!iters) ? pattern : sbwork[!alt], find[i], replace[i]);
        alt = !alt;
      }
      iters++;
      nn += n;
      if (!n) {
        sb << (char*)sbwork[!alt];
        return nn;
      }
    }
  }

  //
  // Input streams
  //

  bool idstream::open(const char* filename, int bufsize) {
    if (fd >= 0) close();
    fd = sys_open(filename, O_RDONLY | O_LARGEFILE, 0);
    error = (fd < 0);
    if (!ok()) return false;
    setbuf(bufsize);
    close_on_destroy = 1;
    return true;
  }

  bool idstream::open(int fd, int bufsize) {
    if (fd >= 0) close();
    this->fd = fd;
    error = (fd < 0);
    if (!ok()) return false;
    setbuf(bufsize);
    close_on_destroy = 0;
    return true;
  }

  int idstream::setbuf(int bufsize) {
    if (buf) {
      assert(this->bufsize > 0);
      delete[] buf;
    }

    this->bufsize = bufsize;

    buf = null;
    if (!bufsize) {
      return 0;
    }

    int bufbits = msbindex(bufsize) + 1;
    bufsize = (1 << bufbits);
    bufmask = bitmask(bufbits-1);

    buf = new byte[bufsize];
    head = 0;
    tail = 0;
    bufused = 0;

    return bufsize;
  }

  int idstream::fillbuf() {
    // For debugging only:
    // cerr << "fillbuf fd ", fd, " (head ", head, ", tail ", tail, ", bufused ", bufused, ", bufsize ", bufsize, ", bufmask ", bufmask, ")", endl, flush;

    if (eos) return 0;

    if (bufused >= (bufsize/2)) return 1;

    if (head < tail) {
      // ....|||||||.....
      //     h      t
      // 0123456789abcdef
      int lobytes = head;
      int hibytes = bufsize - tail;

      int hin = sys_read(fd, &buf[tail], hibytes);
      if (hin < 0) hin = 0;
      if ((hibytes > 0) & (hin == 0)) eos = 1; // end of stream?

      tail = addmod(tail, hin);
      bufused += hin;

      if (hin == hibytes) {
        // do low part
        int lon = sys_read(fd, &buf[0], lobytes);
        if (lon < 0) lon = 0;
        if ((lobytes > 0) & (lon == 0)) eos = 1; // end of stream?
        tail = addmod(tail, lon);
        bufused += lon;
      }
    } else if (head > tail) {
      // ||||.......|||||
      //     t      h
      // 0123456789abcdef

      int bytes = (head - tail);
      int n = sys_read(fd, &buf[tail], bytes);
      if (n < 0) n = 0;

      if ((bytes > 0) & (n == 0)) eos = 1; // end of stream?
      tail = addmod(tail, n);
      bufused += n;
    } else {
      // (head == tail):
      if (bufused) {
        // no action - buffer is full
        assert(bufused == bufsize);
      } else {
        assert(bufused == 0);
        // buffer empty
        int bytes = bufsize;
        int n = sys_read(fd, &buf[0], bytes);
        if (n < 0) n = 0;

        if ((bytes > 0) & (n == 0)) eos = 1; // end of stream?
        head = 0;
        tail = addmod(head, n);
        bufused = n;
      }
    }

    assert(inrange(head, 0, bufsize-1));
    assert(inrange(tail, 0, bufsize-1));
    assert(inrange(bufused, 0, bufsize));

    return 1;
  }

  int idstream::unread(int bytes) {
    assert(bytes <= bufused);
    head = addmod(head, -bytes);
    bufused += bytes;
    assert(inrange(bufused, 0, bufsize));
    assert(inrange(head, 0, bufsize-1));
    assert(inrange(tail, 0, bufsize-1));
    offset -= bytes;
    return bytes;
  }

  int idstream::readbuf(byte* dest, int count) {
    assert(count <= bufsize);
    int n;
    if (head < tail) {
      // ....|||||||.....
      //     h      t
      // 0123456789abcdef
      n = min(bufused, count);
      memcpy(dest, &buf[head], n);
      head = addmod(head, n);
      bufused -= n;
    } else if (head >= tail) {
      // ||||.......|||||
      //     t      h
      // 0123456789abcdef
      n = min(min(bufsize - head, count), bufused);
      memcpy(dest, &buf[head], n);
      head = addmod(head, n);
      bufused -= n;
    }
    assert(inrange(bufused, 0, bufsize));
    return n;
  }

  bool idstream::getc(char& c) {
    if (!buf) return (sys_read(fd, &c, 1) == 1);

    if (!bufused)
      fillbuf();

    if (!bufused) {
      assert(eos);
      error = 1;
      return false;
    }

    c = buf[head];
    head = addmod(head, 1);
    bufused--;
    offset++;
    return true;
  }

  int idstream::read(void* dest, int count) {
    if (!buf) return sys_read(fd, dest, count);

    byte* p = (byte*)dest;
    // Fill the buffer from the tail until the head
    int r = 0;
    while (count) {
      fillbuf();
      int n = readbuf(p, min(count, bufsize));
      if (!n) {
        // end of stream
        error = 1;
        return r;
      }

      r += n;
      p += n;
      count -= n;

      offset += n;
    }

    return r;
  }

  void idstream::close() {
    if (fd >= 0) sys_close(fd);
    if (buf) {
      delete[] buf;
      buf = null;
    }
    fd = -1;
    head = 0;
    tail = 0;
    bufused = 0;
    bufmask = 0;
    eos = 0;
    error = 0;
  }

  int idstream::readline(char* v, int len) {
    if (!len) return 0;

    if (!ok()) {
      v[0] = 0;
      return 0;
    }

    foreach (i, len-1) {
      char c;
      bool ok = getc(c);

      if ((!ok) | (c == '\n') | (c == '\r')) {
        v[i] = 0;
        return i;
      }

      v[i] = c;
    }

    v[len-1] = 0;
    return len-1;
  }

  int idstream::readline(stringbuf& sb) {
    if (!ok()) return 0;

    for (;;) {
      char c;
      bool ok = getc(c);

      if ((!ok) | (c == '\n') | (c == '\r')) return sb.size();

      sb << c;
    }

    return sb.size();
  }

  W64 idstream::seek(W64 pos, int whence) {
    bufused = 0;
    head = 0;
    tail = 0;
    error = 0;
    eos = 0;
    offset = sys_seek(fd, pos, whence);
    return offset;
  }

  W64 idstream::where() const {
    return offset;
  }

  W64 idstream::size() const {
    W64 oldpos = where();
    W64 s = sys_seek(fd, 0, SEEK_END);
    sys_seek(fd, oldpos, SEEK_SET);
    return s;
  }

  void* idstream::mmap(long long size) {
    void* p = sys_mmap(NULL, size, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, filehandle(), 0);
#ifdef __x86_64__
    if ((W64s)p == -1LL) return null;
#else
    if ((W32)p == -1) return null;
#endif
    return p;
  }

  template <>
  char* dynarray<char*>::tokenize(char* string, const char* seplist) {
    byte issep[256];
    setzero(issep);
    foreach (i, strlen(seplist)) { issep[(byte)seplist[i]] = 1; }

    char* pbase = string;
    char* p = pbase;

    while (*p) {
      while ((*p) && issep[*p]) p++;
      if unlikely (!(*p)) break;
      push(p);
      while ((*p) && (!issep[*p])) p++;
      int k = (!!(*p));
      *p = 0;
      p += k;
    }

    return pbase;
  }

  //
  // class RandomNumberGenerator:
  //
  void RandomNumberGenerator::reseed(W32 seed) {
    if unlikely (seed == 0) seed = 1; // default seed is 1
    
#define LCG(n) (69069 * n)
    s1 = LCG(seed);
    s2 = LCG(s1);
    s3 = LCG(s2);
#undef LCG
    
    // warm it up
    foreach (i, 8) random32();
  }
  
  W32 RandomNumberGenerator::random32() {
#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
    
    s1 = TAUSWORTHE(s1, 13, 19, 4294967294UL, 12);
    s2 = TAUSWORTHE(s2, 2, 25, 4294967288UL, 4);
    s3 = TAUSWORTHE(s3, 3, 11, 4294967280UL, 17);
    
    return (s1 ^ s2 ^ s3);
  }
  
  W64 RandomNumberGenerator::random64() {
    return (W64(random32()) << 32) | W64(random32());
  }

  void RandomNumberGenerator::fill(void* p, size_t count) {
    size_t wc = count / sizeof(W32);
    W32* wp = (W32*)p;
    foreach (i, wc) {
      *wp = random32();
      wp++;
    }

    size_t loc = count % sizeof(W32);
    if likely (!loc) return;

    W32 temp = random32();
    byte* lop = (byte*)wp;
    foreach (i, loc) {
      lop[i] = lowbits(temp, 8);
      temp >>= 8;
    }
  }

  //
  // class CycleTimer:
  //
  double CycleTimer::gethz() {
    //
    // Parse the Linux /proc/cpuinfo metafile to find
    // the first CPU's clock speed.
    //
    // NOTE! Processors that do dynamic frequency
    // scaling and report the current frequency in
    // /proc/cpuinfo (versus the nominal peak frequency)
    // will break this. The AMD K7 and K8 architectures
    // fall into this category. Therefore, we try to read
    // the cpuinfo_max_freq key from sysfs and if present
    // we use this value instead.
    //
    if (hz)
      return hz;

    hz = get_core_freq_hz();

    return hz;
  }

  double CycleTimer::hz = 0;

  ostream& operator <<(ostream& os, const CycleTimer& ct) {
    double seconds = ((double)ct.total / ct.gethz());
    os << "CycleTimer ", padstring(ct.title, -16), " ", intstring(ct.total, 16), " cycles, ", 
      floatstring(seconds, 9, 3), " seconds, ", 
      floatstring((float)ct.total / (float)ct.iterations, 18, 1), " cycles/iter, ", 
      floatstring((float)ct.iterations / (float)seconds, 18, 1), " iters/second";

    return os;
  }

  //
  // x86 compatible non-excepting divide and remainder:
  //
  // This code is heavily modified from the Bochs version:
  //
  struct W128 {
    W64 lo;
    W64 hi;
  };

  struct W128s {
    W64 lo;
    W64s hi;
  };

  void long_neg(W128s& n) {
    W64 t = n.lo;
    n.lo = -n.lo;
    if (t - 1 > t) --n.hi;
    n.hi = ~n.hi;
  }

  void long_shl(W128& a) {
    W64 c;
    c = a.lo >> 63;
    a.lo <<= 1;
    a.hi <<= 1;
    a.hi |= c;
  }

  void long_shr(W128& a) {
    W64 c;
    c = a.hi << 63;
    a.hi >>= 1;
    a.lo >>= 1;
    a.lo |= c;
  }

  bool long_sub(W128& a, W128& b) {
    W64 t = a.lo;
    a.lo -= b.lo;
    int c = (a.lo > t);
    t = a.hi;
    a.hi -= b.hi + c;
    return (a.hi > t);
  }

  bool long_le(W128& a, W128& b) {
    if (a.hi == b.hi) {
      return (a.lo <= b.lo);
    } else {
      return (a.hi <= b.hi);
    }
  }

  void long_div(W128& quotient, W64& remainder, const W128& dividend, W64 divisor) {
    W128 d, acc, q, temp;
    int n, c;

    d.lo = divisor;
    d.hi = 0;
    acc.lo = dividend.lo;
    acc.hi = dividend.hi;
    q.lo = 0;
    q.hi = 0;
    n = 0;

    while (long_le(d, acc) && (n < 128)) {
      long_shl(d);
      n++;
    }

    while (n > 0) {
      long_shr(d);
      long_shl(q);
      temp.lo = acc.lo;
      temp.hi = acc.hi;
      c = long_sub(acc, d);
      if (c) {
        acc.lo = temp.lo;
        acc.hi = temp.hi;
      } else {
        q.lo++;
      }
      n--;
    }

    remainder = acc.lo;
    quotient.lo = q.lo;
    quotient.hi = q.hi;
  }

  void long_idiv(W128s& quotient, W64s& remainder, W128s& dividend, W64s divisor) {
    W128s temp = dividend;

    bool dividend_was_negative = (temp.hi < 0);
    bool divisor_was_negative = (divisor < 0);
    if (dividend_was_negative) long_neg(temp);
    if (divisor_was_negative) divisor = -divisor;

    long_div((W128&)quotient, (W64&)remainder, (W128&)temp, divisor);

    if (dividend_was_negative ^ divisor_was_negative) long_neg(quotient);

    // NOTE: Bochs original code was: if (divisor_was_negative) remainder = -remainder;
    // This is actually a bug: Intel and AMD manuals say sign of remainder is equal to sign of dividend, not divisor.
    if (dividend_was_negative) remainder = -remainder;
  }

  template <>
  bool div_rem(W64& quotientlo, W64& remainder, W64 dividend_hi, W64 dividend_lo, W64 divisor) {
    W128 dividend;
    W128 quotient;

    dividend.lo = dividend_lo;
    dividend.hi = dividend_hi;

    if unlikely (!divisor) goto out;

    long_div(quotient, remainder, dividend, divisor);
    quotientlo = quotient.lo;

    if unlikely (quotient.hi != 0) goto out;

    return true;

  out:
    quotientlo = 0;
    remainder = 0;
    return false;
  }

  template <>
  bool div_rem_s(W64& quotientlo, W64& remainder, W64 dividend_hi, W64 dividend_lo, W64 divisor) {
    W64s op2_64, remainder_64, quotient_64l;
    W128s dividend;
    W128s quotient;

    dividend.lo = dividend_lo;
    dividend.hi = dividend_hi;

    if unlikely (!divisor) goto out;

    if unlikely ((divisor == -1) && (dividend.hi == 0x8000000000000000ULL) && (!dividend.lo)) goto out;

    long_idiv(quotient, (W64s&)remainder, dividend, divisor);
    quotientlo = quotient.lo;

    if unlikely ((!(quotient.lo & 0x8000000000000000ULL) && quotient.hi != 0) ||
                 (quotient.lo & 0x8000000000000000ULL) && quotient.hi != 0xffffffffffffffffULL) goto out;

    return true;

  out:
    quotientlo = 0;
    remainder = 0;
    return false;
  }

  template <typename T>
  bool div_rem(T& quotientlo, T& remainder, T dividend_hi, T dividend_lo, T divisor) {
    static const int B = (sizeof(T) * 8);

    W64 dividend = (W64(dividend_hi) << B) + dividend_lo;
    W64 quotient;

    if unlikely (divisor == 0) goto out;

    quotient  = dividend / divisor;
    remainder = T(dividend % divisor);
    quotientlo = T(quotient);

    if unlikely (quotient != quotientlo) goto out;

    return true;

  out:
    quotientlo = 0;
    remainder = 0;
    return false;
  }

  template <typename T>
  bool div_rem_s(T& quotientlo, T& remainder, T dividend_hi, T dividend_lo, T udivisor) {
    static const int B = (sizeof(T) * 8);

    W64s dividend = (W64(signext64(dividend_hi, B)) << B) + dividend_lo;
    W64 quotient;
    W64s divisor = signext64(W64(udivisor), B);

    if unlikely (divisor == 0) goto out;

    // check MIN_INT divided by -1 case
    // e.g. MIN_INT for 32/16/8 = 0x8000000000000000ULL, 0x80000000ULL, 0x8000ULL
    if unlikely ((dividend == signext64((1ULL << ((B*2) - 1)), (B*2))) && (divisor == bitmask(B))) goto out;

    quotient = dividend / divisor;
    remainder = T(dividend % divisor);
    quotientlo = T(quotient);
  
    if unlikely (quotient != signext64(W64(quotientlo), B)) goto out;

    return true;

  out:
    quotientlo = 0;
    remainder = 0;
    return false;
  }

#define decl_div_rem(T) template bool div_rem(T& quotient, T& remainder, T dividend_hi, T dividend_lo, T divisor);
#define decl_div_rem_s(T) template bool div_rem_s(T& quotient, T& remainder, T dividend_hi, T dividend_lo, T divisor);

  decl_div_rem(W8);
  decl_div_rem(W16);
  decl_div_rem(W32);
  decl_div_rem(W64);

  decl_div_rem_s(W8);
  decl_div_rem_s(W16);
  decl_div_rem_s(W32);
  decl_div_rem_s(W64);

  //
  // Global streams:
  //

  istream cin(0);
  ostream cout(1);
  ostream cerr(2);

  static void close_streams() {
    cout.flush();
    cerr.flush();
  }

  struct ExitCallbacks {
    ExitCallbacks(bool x) { assert(atexit(close_streams) == 0); }
  };
  // Add to the automatic ctors list:
  // Note that this only works on non-standalone code (i.e., not using klibc):
  ExitCallbacks callbacks(true);
};

using namespace superstl;

char* format_number(char* buf, char* end, W64 num, int base, int size, int precision, int type) {
	char c,sign,tmp[66];
	const char *digits;
	static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
	static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int i;

	digits = (type & FMT_LARGE) ? large_digits : small_digits;
	if (type & FMT_LEFT)
		type &= ~FMT_ZEROPAD;
	if (base < 2 || base > 36)
		return NULL;
	c = (type & FMT_ZEROPAD) ? '0' : ' ';
	sign = 0;
	if (type & FMT_SIGN) {
		if ((signed long long) num < 0) {
			sign = '-';
			num = - (signed long long) num;
			size--;
		} else if (type & FMT_PLUS) {
			sign = '+';
			size--;
		} else if (type & FMT_SPACE) {
			sign = ' ';
			size--;
		}
	}
	if (type & FMT_SPECIAL) {
		if (base == 16)
			size -= 2;
		else if (base == 8)
			size--;
	}
	i = 0;
	if (num == 0)
		tmp[i++]='0';
	else while (num != 0)
		tmp[i++] = digits[do_div(num,base)];
	if (i > precision)
		precision = i;
	size -= precision;
	if (!(type&(FMT_ZEROPAD+FMT_LEFT))) {
		while(size-->0) {
			if (buf <= end)
				*buf = ' ';
			++buf;
		}
	}
	if (sign) {
		if (buf <= end)
			*buf = sign;
		++buf;
	}
	if (type & FMT_SPECIAL) {
		if (base==8) {
			if (buf <= end)
				*buf = '0';
			++buf;
		} else if (base==16) {
			if (buf <= end)
				*buf = '0';
			++buf;
			if (buf <= end)
				*buf = digits[33];
			++buf;
		}
	}
	if (!(type & FMT_LEFT)) {
		while (size-- > 0) {
			if (buf <= end)
				*buf = c;
			++buf;
		}
	}
	while (i < precision--) {
		if (buf <= end)
			*buf = '0';
		++buf;
	}
	while (i-- > 0) {
		if (buf <= end)
			*buf = tmp[i];
		++buf;
	}
	while (size-- > 0) {
		if (buf <= end)
			*buf = ' ';
		++buf;
	}
	return buf;
}

int format_integer(char* buf, int bufsize, W64s v, int size, int flags, int base, int precision) {
  if (size < 0) size = bufsize-1;
  if ((v < 0) & (base == 10)) flags ^= FMT_SIGN;
  char* end = format_number(buf, buf + bufsize - 2, v, base, min(bufsize-1, size), precision, flags);
  // null terminate
  *end = 0;
  return (end - buf);
}

const unsigned char popcountlut8bit[] = {
  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
  4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};

const byte lsbindexlut8bit[256] = {
  0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

const W32 CRC32::crctable[256] = {
  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  0x2d02ef8dL
};

ostream& operator <<(ostream& os, const vec16b& v) {
  // Print as hex
  byte* b = (byte*)&v;
  for (int i = 15; i >= 0; i--) {
    if (i < 15) os << ((i == 7) ? '.' : ' ');
    os << hexstring(b[i], 8);
  }
  return os;

#if 0
  // Print as decimal:
  byte* b = (byte*)&v;
  for (int i = 0; i < 16; i++) {
    if (i) os << ' ';
    os << intstring(b[i], 3);
  }
  return os;
#endif
}

ostream& operator ,(ostream& os, const vec16b& v) {
  return os << v;
}

ostream& operator <<(ostream& os, const vec8w& v) {
  W16* b = (W16*)&v;
  for (int i = 0; i < 8; i++) {
    if (i) os << ' ';
    os << intstring(b[i], 5);
  }
  return os;
}


ostream& operator ,(ostream& os, const vec8w& v) {
  return os << v;
}

const byte byte_to_vec16b[256][16] alignto(16) = {
  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
  {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02},
  {0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03},
  {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04},
  {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05},
  {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
  {0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07},
  {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08},
  {0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09},
  {0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a},
  {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
  {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
  {0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d},
  {0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e},
  {0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},
  {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
  {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
  {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12},
  {0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13},
  {0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14},
  {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15},
  {0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16},
  {0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17},
  {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
  {0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19},
  {0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a},
  {0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b},
  {0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
  {0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d},
  {0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e},
  {0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f},
  {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20},
  {0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21},
  {0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},
  {0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23},
  {0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24},
  {0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25},
  {0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26},
  {0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27},
  {0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28},
  {0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29},
  {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a},
  {0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b},
  {0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c},
  {0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d},
  {0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e},
  {0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f},
  {0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
  {0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31},
  {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
  {0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33},
  {0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34},
  {0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35},
  {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
  {0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37},
  {0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38},
  {0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39},
  {0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a},
  {0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b},
  {0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c},
  {0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d},
  {0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e},
  {0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f},
  {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40},
  {0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
  {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42},
  {0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43},
  {0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44},
  {0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45},
  {0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46},
  {0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47},
  {0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48},
  {0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49},
  {0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a},
  {0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b},
  {0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c},
  {0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d},
  {0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e},
  {0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f},
  {0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50},
  {0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51},
  {0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52},
  {0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53},
  {0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54},
  {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55},
  {0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56},
  {0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57},
  {0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58},
  {0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59},
  {0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a},
  {0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b},
  {0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c},
  {0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d},
  {0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e},
  {0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f},
  {0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60},
  {0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61},
  {0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62},
  {0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63},
  {0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64},
  {0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65},
  {0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66},
  {0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67},
  {0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68},
  {0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69},
  {0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a},
  {0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b},
  {0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c},
  {0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d},
  {0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e},
  {0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f},
  {0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70},
  {0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71},
  {0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72},
  {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73},
  {0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74},
  {0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75},
  {0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76},
  {0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77},
  {0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78},
  {0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79},
  {0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a},
  {0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b},
  {0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c},
  {0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d},
  {0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e},
  {0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f},
  {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
  {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81},
  {0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82},
  {0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83},
  {0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84},
  {0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85},
  {0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86},
  {0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87},
  {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88},
  {0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89},
  {0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a},
  {0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b},
  {0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c},
  {0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d},
  {0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e},
  {0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f},
  {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90},
  {0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91},
  {0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92},
  {0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93},
  {0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94},
  {0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95},
  {0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96},
  {0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97},
  {0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98},
  {0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99},
  {0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a},
  {0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b},
  {0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c},
  {0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d},
  {0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e},
  {0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f},
  {0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0},
  {0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1},
  {0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2},
  {0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3},
  {0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4},
  {0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5},
  {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6},
  {0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7},
  {0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8},
  {0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9},
  {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
  {0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab},
  {0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac},
  {0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad},
  {0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae},
  {0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf},
  {0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0},
  {0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1},
  {0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2},
  {0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3},
  {0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4},
  {0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5},
  {0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6},
  {0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7},
  {0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8},
  {0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9},
  {0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba},
  {0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb},
  {0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc},
  {0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd},
  {0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe},
  {0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf},
  {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
  {0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1},
  {0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2},
  {0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
  {0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4},
  {0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5},
  {0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6},
  {0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7},
  {0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8},
  {0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9},
  {0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca},
  {0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb},
  {0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc},
  {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd},
  {0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce},
  {0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf},
  {0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0},
  {0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1},
  {0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2},
  {0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3},
  {0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4},
  {0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5},
  {0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6},
  {0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7},
  {0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8},
  {0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9},
  {0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda},
  {0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb},
  {0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc},
  {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd},
  {0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde},
  {0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf},
  {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0},
  {0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1},
  {0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2},
  {0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3},
  {0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4},
  {0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5},
  {0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6},
  {0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7},
  {0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8},
  {0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9},
  {0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea},
  {0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb},
  {0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec},
  {0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed},
  {0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee},
  {0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef},
  {0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0},
  {0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1},
  {0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2},
  {0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3},
  {0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4},
  {0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5},
  {0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6},
  {0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7},
  {0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8},
  {0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9},
  {0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa},
  {0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
  {0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc},
  {0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd},
  {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe},
  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
};

const byte index_bytes_vec16b[16][16] alignto(16) = {
  {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
  {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f},
  {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f},
  {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f},
  {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f},
  {0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f},
  {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f},
  {0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f},
  {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f},
  {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f},
  {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf},
  {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf},
  {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf},
  {0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf},
  {0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef},
  {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff},
};

const byte index_bytes_plus1_vec16b[16][16] alignto(16) = {
  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
  0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
  0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
  0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
  0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
  0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
  0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
  0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
  0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
  0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
  0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
  0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
  0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
  0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00, // element 255 not valid!
};

const W64 expand_8bit_to_64bit_lut[256] alignto(8) = {
  0x0000000000000000ULL,   0x00000000000000ffULL,   0x000000000000ff00ULL,   0x000000000000ffffULL,
  0x0000000000ff0000ULL,   0x0000000000ff00ffULL,   0x0000000000ffff00ULL,   0x0000000000ffffffULL,
  0x00000000ff000000ULL,   0x00000000ff0000ffULL,   0x00000000ff00ff00ULL,   0x00000000ff00ffffULL,
  0x00000000ffff0000ULL,   0x00000000ffff00ffULL,   0x00000000ffffff00ULL,   0x00000000ffffffffULL,
  0x000000ff00000000ULL,   0x000000ff000000ffULL,   0x000000ff0000ff00ULL,   0x000000ff0000ffffULL,
  0x000000ff00ff0000ULL,   0x000000ff00ff00ffULL,   0x000000ff00ffff00ULL,   0x000000ff00ffffffULL,
  0x000000ffff000000ULL,   0x000000ffff0000ffULL,   0x000000ffff00ff00ULL,   0x000000ffff00ffffULL,
  0x000000ffffff0000ULL,   0x000000ffffff00ffULL,   0x000000ffffffff00ULL,   0x000000ffffffffffULL,
  0x0000ff0000000000ULL,   0x0000ff00000000ffULL,   0x0000ff000000ff00ULL,   0x0000ff000000ffffULL,
  0x0000ff0000ff0000ULL,   0x0000ff0000ff00ffULL,   0x0000ff0000ffff00ULL,   0x0000ff0000ffffffULL,
  0x0000ff00ff000000ULL,   0x0000ff00ff0000ffULL,   0x0000ff00ff00ff00ULL,   0x0000ff00ff00ffffULL,
  0x0000ff00ffff0000ULL,   0x0000ff00ffff00ffULL,   0x0000ff00ffffff00ULL,   0x0000ff00ffffffffULL,
  0x0000ffff00000000ULL,   0x0000ffff000000ffULL,   0x0000ffff0000ff00ULL,   0x0000ffff0000ffffULL,
  0x0000ffff00ff0000ULL,   0x0000ffff00ff00ffULL,   0x0000ffff00ffff00ULL,   0x0000ffff00ffffffULL,
  0x0000ffffff000000ULL,   0x0000ffffff0000ffULL,   0x0000ffffff00ff00ULL,   0x0000ffffff00ffffULL,
  0x0000ffffffff0000ULL,   0x0000ffffffff00ffULL,   0x0000ffffffffff00ULL,   0x0000ffffffffffffULL,
  0x00ff000000000000ULL,   0x00ff0000000000ffULL,   0x00ff00000000ff00ULL,   0x00ff00000000ffffULL,
  0x00ff000000ff0000ULL,   0x00ff000000ff00ffULL,   0x00ff000000ffff00ULL,   0x00ff000000ffffffULL,
  0x00ff0000ff000000ULL,   0x00ff0000ff0000ffULL,   0x00ff0000ff00ff00ULL,   0x00ff0000ff00ffffULL,
  0x00ff0000ffff0000ULL,   0x00ff0000ffff00ffULL,   0x00ff0000ffffff00ULL,   0x00ff0000ffffffffULL,
  0x00ff00ff00000000ULL,   0x00ff00ff000000ffULL,   0x00ff00ff0000ff00ULL,   0x00ff00ff0000ffffULL,
  0x00ff00ff00ff0000ULL,   0x00ff00ff00ff00ffULL,   0x00ff00ff00ffff00ULL,   0x00ff00ff00ffffffULL,
  0x00ff00ffff000000ULL,   0x00ff00ffff0000ffULL,   0x00ff00ffff00ff00ULL,   0x00ff00ffff00ffffULL,
  0x00ff00ffffff0000ULL,   0x00ff00ffffff00ffULL,   0x00ff00ffffffff00ULL,   0x00ff00ffffffffffULL,
  0x00ffff0000000000ULL,   0x00ffff00000000ffULL,   0x00ffff000000ff00ULL,   0x00ffff000000ffffULL,
  0x00ffff0000ff0000ULL,   0x00ffff0000ff00ffULL,   0x00ffff0000ffff00ULL,   0x00ffff0000ffffffULL,
  0x00ffff00ff000000ULL,   0x00ffff00ff0000ffULL,   0x00ffff00ff00ff00ULL,   0x00ffff00ff00ffffULL,
  0x00ffff00ffff0000ULL,   0x00ffff00ffff00ffULL,   0x00ffff00ffffff00ULL,   0x00ffff00ffffffffULL,
  0x00ffffff00000000ULL,   0x00ffffff000000ffULL,   0x00ffffff0000ff00ULL,   0x00ffffff0000ffffULL,
  0x00ffffff00ff0000ULL,   0x00ffffff00ff00ffULL,   0x00ffffff00ffff00ULL,   0x00ffffff00ffffffULL,
  0x00ffffffff000000ULL,   0x00ffffffff0000ffULL,   0x00ffffffff00ff00ULL,   0x00ffffffff00ffffULL,
  0x00ffffffffff0000ULL,   0x00ffffffffff00ffULL,   0x00ffffffffffff00ULL,   0x00ffffffffffffffULL,
  0xff00000000000000ULL,   0xff000000000000ffULL,   0xff0000000000ff00ULL,   0xff0000000000ffffULL,
  0xff00000000ff0000ULL,   0xff00000000ff00ffULL,   0xff00000000ffff00ULL,   0xff00000000ffffffULL,
  0xff000000ff000000ULL,   0xff000000ff0000ffULL,   0xff000000ff00ff00ULL,   0xff000000ff00ffffULL,
  0xff000000ffff0000ULL,   0xff000000ffff00ffULL,   0xff000000ffffff00ULL,   0xff000000ffffffffULL,
  0xff0000ff00000000ULL,   0xff0000ff000000ffULL,   0xff0000ff0000ff00ULL,   0xff0000ff0000ffffULL,
  0xff0000ff00ff0000ULL,   0xff0000ff00ff00ffULL,   0xff0000ff00ffff00ULL,   0xff0000ff00ffffffULL,
  0xff0000ffff000000ULL,   0xff0000ffff0000ffULL,   0xff0000ffff00ff00ULL,   0xff0000ffff00ffffULL,
  0xff0000ffffff0000ULL,   0xff0000ffffff00ffULL,   0xff0000ffffffff00ULL,   0xff0000ffffffffffULL,
  0xff00ff0000000000ULL,   0xff00ff00000000ffULL,   0xff00ff000000ff00ULL,   0xff00ff000000ffffULL,
  0xff00ff0000ff0000ULL,   0xff00ff0000ff00ffULL,   0xff00ff0000ffff00ULL,   0xff00ff0000ffffffULL,
  0xff00ff00ff000000ULL,   0xff00ff00ff0000ffULL,   0xff00ff00ff00ff00ULL,   0xff00ff00ff00ffffULL,
  0xff00ff00ffff0000ULL,   0xff00ff00ffff00ffULL,   0xff00ff00ffffff00ULL,   0xff00ff00ffffffffULL,
  0xff00ffff00000000ULL,   0xff00ffff000000ffULL,   0xff00ffff0000ff00ULL,   0xff00ffff0000ffffULL,
  0xff00ffff00ff0000ULL,   0xff00ffff00ff00ffULL,   0xff00ffff00ffff00ULL,   0xff00ffff00ffffffULL,
  0xff00ffffff000000ULL,   0xff00ffffff0000ffULL,   0xff00ffffff00ff00ULL,   0xff00ffffff00ffffULL,
  0xff00ffffffff0000ULL,   0xff00ffffffff00ffULL,   0xff00ffffffffff00ULL,   0xff00ffffffffffffULL,
  0xffff000000000000ULL,   0xffff0000000000ffULL,   0xffff00000000ff00ULL,   0xffff00000000ffffULL,
  0xffff000000ff0000ULL,   0xffff000000ff00ffULL,   0xffff000000ffff00ULL,   0xffff000000ffffffULL,
  0xffff0000ff000000ULL,   0xffff0000ff0000ffULL,   0xffff0000ff00ff00ULL,   0xffff0000ff00ffffULL,
  0xffff0000ffff0000ULL,   0xffff0000ffff00ffULL,   0xffff0000ffffff00ULL,   0xffff0000ffffffffULL,
  0xffff00ff00000000ULL,   0xffff00ff000000ffULL,   0xffff00ff0000ff00ULL,   0xffff00ff0000ffffULL,
  0xffff00ff00ff0000ULL,   0xffff00ff00ff00ffULL,   0xffff00ff00ffff00ULL,   0xffff00ff00ffffffULL,
  0xffff00ffff000000ULL,   0xffff00ffff0000ffULL,   0xffff00ffff00ff00ULL,   0xffff00ffff00ffffULL,
  0xffff00ffffff0000ULL,   0xffff00ffffff00ffULL,   0xffff00ffffffff00ULL,   0xffff00ffffffffffULL,
  0xffffff0000000000ULL,   0xffffff00000000ffULL,   0xffffff000000ff00ULL,   0xffffff000000ffffULL,
  0xffffff0000ff0000ULL,   0xffffff0000ff00ffULL,   0xffffff0000ffff00ULL,   0xffffff0000ffffffULL,
  0xffffff00ff000000ULL,   0xffffff00ff0000ffULL,   0xffffff00ff00ff00ULL,   0xffffff00ff00ffffULL,
  0xffffff00ffff0000ULL,   0xffffff00ffff00ffULL,   0xffffff00ffffff00ULL,   0xffffff00ffffffffULL,
  0xffffffff00000000ULL,   0xffffffff000000ffULL,   0xffffffff0000ff00ULL,   0xffffffff0000ffffULL,
  0xffffffff00ff0000ULL,   0xffffffff00ff00ffULL,   0xffffffff00ffff00ULL,   0xffffffff00ffffffULL,
  0xffffffffff000000ULL,   0xffffffffff0000ffULL,   0xffffffffff00ff00ULL,   0xffffffffff00ffffULL,
  0xffffffffffff0000ULL,   0xffffffffffff00ffULL,   0xffffffffffffff00ULL,   0xffffffffffffffffULL,
};
